/**
 * RecvControlCmd.java
 * 版权所有(C) 2013
 * 创建者:cuiran 2013-11-27 上午11:48:19
 */
package com.ghyf.mplay.net.common;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.ghyf.mplay.bean.GlobalParamInfo;
import com.ghyf.mplay.net.data.CurDisplayData;
import com.ghyf.mplay.util.LogUtil;
import com.ghyf.mplay.util.ScreenShotFb;
import com.ghyf.mplay.value.ConstantValue;





/**
 * 设备控制接收
 * @author cuiran
 * @version 1.0.0
 */
public class RecvControlCmd extends RecvBase implements Runnable {

	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public RecvControlCmd(int listenPort, int serverPort,Context context){
		port_listen = listenPort;
		port_server = serverPort;
		mContext=context;
	}

	public void run() {
		LogUtil.i(TAG, "RecvControlCmd.run() -- start!");
		try
		{
			LogUtil.i(TAG, "RecvControlCmd.run() -- try....");
			
			DatagramSocket so_out = new DatagramSocket();
			DatagramSocket so_in = new DatagramSocket(port_listen);
			LogUtil.i(TAG, "RecvControlCmd.run() -- Recv Socket Created!");
			so_in.setSoTimeout(100);
			
			byte[] buf_in = new byte[GData.maxPacketLength];
			DatagramPacket pkt_in = new DatagramPacket(buf_in, buf_in.length);
			byte[] buf_in1 = new byte[GData.maxPacketLength];
			LogUtil.i(TAG, "RecvControlCmd.run() -- Recv Pakcet Created!");
			
		//	LogUtil.i(TAG, "RecvControlCmd.run() -- Begin Receiving...");
			while(!isStop)
			{
				try
				{
					so_in.receive(pkt_in);
			//		LogUtil.i(TAG, "RecvControlCmd.run() -- receiv() returned!");
					LogUtil.i(TAG, "RecvControlCmd.run() -- Recv PacketLength(" + pkt_in.getLength() + ")");
				
					// Check Packet Length
					int recvLength = pkt_in.getLength();
					if(recvLength < packetHeaderLength)
					{
						LogUtil.i(TAG, "RecvControlCmd.run() -- Received bad Packet, Length=" + recvLength);
						continue;
					}
					
					// Analyse the Packet Header
					byte[] buf_recv = pkt_in.getData();
					assert(buf_recv.length == recvLength);
					ByteArrayInputStream baInPacketHeader = new ByteArrayInputStream(buf_recv, 0, packetHeaderLength);
					DataInputStream dInHeader = new DataInputStream(baInPacketHeader);
					byte stx = dInHeader.readByte();
					short cmdID = dInHeader.readShort();
					int timestamp = dInHeader.readInt();
					int tickCount = dInHeader.readInt();
					byte[] buf_temp = new byte[recvLength];
					dInHeader.read(buf_temp, 0, deviceIDLength);
					String deviceID = new String(buf_temp, 0, deviceIDLength,RecvBase.charset).trim();
					dInHeader.skipBytes(packetHeaderReservedLength);
					short dataLength = dInHeader.readShort();
					
					// Check & LogUtil
					if(stx != STX_SERVER2CLIENT || dataLength + packetHeaderLength != recvLength)
					{
						LogUtil.i(TAG, "RecvControlCmd.run() -- Received BAD Packet, stx=" + stx + " cmdID=" + cmdID + 
								" timestamp=" + timestamp + "tickCount=" + tickCount + " deviceID=" + deviceID + " recvLength=" + recvLength+" dataLength="+dataLength);
						continue;
					}
					LogUtil.i(TAG, "RecvControlCmd.run() -- Received Control Packet, stx=" + stx + " cmdID=" + cmdID + 
							" timestamp=" + timestamp + "tickCount=" + tickCount + " deviceID=" + deviceID + " recvLength=" + recvLength);

					// Get server address
					InetAddress inetAddr_in = pkt_in.getAddress();
					String ip_in = inetAddr_in.getHostAddress();
					int port_in = pkt_in.getPort();
					LogUtil.i(TAG, "RecvControlCmd.run() -- Recv Packet from: IP(" + ip_in + ":" + port_in + ") Length(" + pkt_in.getLength() + ")");
					
					// Analyse Cmd Data
					switch(cmdID)
					{
					case CMD_STATUS_REQUEST:
					{
					//	SendStatusReport(inetAddr_in, port_server);	
						//byte[] buf_out = MakeStatusReportPacket();
						//DatagramPacket pkt_out = new DatagramPacket(buf_out, buf_out.length, inetAddr_in, port_server);
				        //so_out.send(pkt_out);
				        //LogUtil.i(TAG, "RecvControlCmd.run() -- Send StatusReportPacket to: IP(" + ip_in + ":" + port_server + ") Length(" + pkt_out.getLength() + ")");
						break;
					}
					case CMD_STATUS_GETCURDIAPLAY:
					{
						/**
						 * 获取参数
						 */
						CurDisplayData data=new CurDisplayData();
						data.getCurDisplay(buf_recv, packetHeaderLength, curDisplayDataLength);
								
						//	new a thread to send current display to server!
					
//						Intent mIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);
//						mIntent.putExtra("cmd", cmdID);
//						Bundle bundle=new Bundle();
//						bundle.putSerializable(ConstantValue.EXTRA_OBJ, data);
//						mIntent.putExtra(ConstantValue.EXTRA_BUNDLE, bundle);
//						//发送广播
//						mContext.sendBroadcast(mIntent);
						 new Thread() {
					            public void run() {
					                try { 
					                	ScreenShotFb.shot();
					                } catch (Exception e) {
					                    e.printStackTrace();
					                } finally {
					                   
					                }
					            }
					        }.start();
						// sendAck
						String strExecDes = new String("已收到获取当前播放画面指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);
						
					
						break;
					}
					case CMD_CONTROL_POWERON:
					{
						// first, sendAck 
						String strExecDes = new String("已收到设备唤醒控制指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);

				        // then, Do Power on System here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
						
						break;
					}
					case CMD_CONTROL_POWEROFF:
					{
						// first, sendAck 
						String strExecDes = new String("已收到设备关机指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);

				        //then,  Do Power off System here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
						
						break;
					}
					case CMD_CONTROL_SCREENON:
					{
						/**
						 *  Mode		WORD	2	0	附加命令。0=没有附件命令；1=先执行附加命令，再执行本命令；2=先执行本命令，再执行附加命令。
							CmdID		WORD	2		例如：Cmd.Serial.Request	附加命令ID
							DataLength	WORD	2		附加命令数据长度
							Data	-	变长	-	
						 */
						
						
						break;
					}
					case CMD_CONTROL_SCREENOFF:
					{
						
						
						break;
					}
					case CMD_CONTROL_RESET:
					{
						// first, sendAck 
						String strExecDes = new String("已收到设备重启指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);

				        // then, Restart System here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
						
						break;
					}
					case CMD_CONTROL_RESTARTSOFTWARE:
					{
						// first, sendAck 
						String strExecDes = new String("已收到软件重启指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);
						LogUtil.i(TAG, "first, sendAck "+cmdID);
				        // then, Restart SoftWare here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
						
						break;
					}
					case CMD_CONTROL_PLAY:
					case CMD_CONTROL_STOP:
					case CMD_CONTROL_REPLAY:
					case CMD_CONTROL_PAUSEPLAY:
					{
				        // Do Play/Stop/Pause/etc... Actions here!!
						Intent mIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);
						mIntent.putExtra("cmd", cmdID);
						//发送广播
						mContext.sendBroadcast(mIntent);
						
						// sendAck
						String strExecDes = new String("已收到节目单控制指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);      
						break;
					}
					case CMD_CONTROL_TAKE:
					{
						// sendAck
						String strExecDes = new String("已收到切换模板指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);   
				        // Do Take Actions here!!
						Intent myIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);  
						myIntent.putExtra("cmd", cmdID);
						//发送广播
						mContext.sendBroadcast(myIntent);
					   
						break;
					}
					case CMD_CONTROL_PLAYSTREAM:
					{
						// sendAck
						String strExecDes = new String("已收到节目单控制指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);   
						/**
						 * ~~~~~~~~~~~~~~~~获取直播地址~~~~~~~~~~~~
						 * IP	CHAR	15	‘xxx.xxx.xxx.xxx’	组播地址
						 * Port	DWORD	 4	 n	                                        组播端口号
						 */
						if(recvLength == packetHeaderLength + streamDataLength){
							ByteArrayInputStream baInPacketData = new ByteArrayInputStream(buf_recv, packetHeaderLength, streamDataLength);
							DataInputStream dInData = new DataInputStream(baInPacketData);
							byte[] buf = new byte[20];
							dInData.read(buf, 0, ipDataLength);
							String ip=new String(buf,0,ipDataLength,RecvBase.charset).trim();
							int port=dInData.readInt();
							LogUtil.e(TAG, "收到直播 地址为： ip("+ip+") port("+port+")");
							if(null!=ip&&!"".equals(ip)&&port>0){
								GlobalParamInfo.getInstance().setLive_url(ip+":"+port);
							}
						}
						
				        // Do CMD_CONTROL_PLAYSTREAM here!!
						Intent mIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);
						mIntent.putExtra("cmd", cmdID);
						//发送广播
						mContext.sendBroadcast(mIntent);
						break;
					}
					case CMD_CONTROL_PLAYLOCAL:
					{
						
						// sendAck
						String strExecDes = new String("已收到节目单控制指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);   
						
				        // Do CMD_CONTROL_PLAYLOCAL here!!
						Intent mIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);
						mIntent.putExtra("cmd", cmdID);
						//发送广播
						mContext.sendBroadcast(mIntent);
						   
						break;
					}
					case CMD_CONTROL_SETVOLUME:
					{
						// Get Volume Value 
						if(dataLength != setVolumeDataLength || recvLength != packetHeaderLength + dataLength)
						{
							// send nack
							String strExecDes = new String("I have Received CMD_CONTROL_SETVOLUME CMD, but dataLength(" + dataLength + ") RecvLength(" + recvLength + " Error!");
							sendAck(cmdID, timestamp, tickCount, (short)NET_NAK, (byte)0, strExecDes, so_out, inetAddr_in);      
							break;
						}
//						ByteArrayInputStream baInPacketData = new ByteArrayInputStream(buf_recv, packetHeaderLength, recvLength - packetHeaderLength);
//						DataInputStream dInData = new DataInputStream(baInPacketData);
//						byte recvVolume = dInHeader.readByte();
						byte recvVolume = buf_recv[packetHeaderLength];
						LogUtil.i(TAG, "recvVolume="+recvVolume);
				        // Do volume control here!!
					
						Intent mIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);
						mIntent.putExtra("cmd", cmdID);
						Bundle bundle=new Bundle();
						bundle.putByte("volume", recvVolume);
						mIntent.putExtra(ConstantValue.EXTRA_BUNDLE, bundle);
						//发送广播
						mContext.sendBroadcast(mIntent);
						
						// sendAck 
						String strExecDes = new String("已收到设置音量的指令!");
						strExecDes += " Volume=" + recvVolume;
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);      
						break;
					}
					case CMD_CONTROL_SOUNDON:
					case CMD_CONTROL_SOUNDMUTE:
					{
				        // Do volume control here!!
						Intent mIntent = new Intent(RecvBase.ACTION_CMD_CONTROL);
						mIntent.putExtra("cmd", cmdID);
						//发送广播
						mContext.sendBroadcast(mIntent);
						// sendAck
						String strExecDes = new String("已收到设置静音和恢复静音的指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);      
						break;
					}
					case CMD_CONTROL_STARTEMERGENCY:
					case CMD_CONTROL_STOPEMERGENCY:
					{
				        // Do EMERGENCY control here!!
				        
						// sendAck
						String strExecDes = new String("已收到紧急模板指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);      
						break;
					}
//					case CMD_CONTROL_GETEMERGENCYID:
//					case CMD_CONTROL_GETEMERGENCYTEXT:
//					{
//						break;
//					}
					case CMD_CONTROL_GROUPSHOW:
					case CMD_CONTROL_GROUPHIDE:
					{
						
						short gid=dInHeader.readShort();
						
						LogUtil.i(TAG, "cmdID="+cmdID+" , gid= "+gid);
				        // Do GROUP control here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            myIntent.putExtra(ConstantValue.EXTRA_ID, gid);
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
				        
						// sendAck
						String strExecDes = new String("已收到显示/隐藏指定的组的指令!");
						sendAck(cmdID, timestamp, tickCount, (short)NET_ACK, (byte)0, strExecDes, so_out, inetAddr_in);      
						break;
					}
//					case CMD_LIST_GETCURLIST:
//					case CMD_LIST_GETLISTDATA:
//					case CMD_LIST_DELETE:
//					case CMD_LIST_PLAY:
//					{
//						break;
//					}
//					case CMD_FILE_SETCONFIG:
//					case CMD_FILE_SETLIST:
//					{
//						break;
//					}
					case CMD_SERIAL_REQUEST:
					case CMD_SERIAL_REPORT:					//
					{
						ByteArrayInputStream baInPacketData = new ByteArrayInputStream(buf_recv, packetHeaderLength, recvLength - packetHeaderLength);
						DataInputStream dInData = new DataInputStream(baInPacketData);
						byte commNum = dInData.readByte();
						LogUtil.i(TAG, "commNum="+commNum+"  ");
						byte [] data=new byte[4];
						dInData.read(data);
						
						for(int i=0;i<4;i++){
							LogUtil.i(TAG, "data="+data[i]);
						}
						if(commNum<=0){
							int serial=GlobalParamInfo.getInstance().getSerial();
							if(serial>0){
								commNum=(byte)serial;
							}
						}
				        // Do GROUP control here!!
						Intent myIntent = new Intent(ConstantValue.CMD_RECEIVER);  
			            myIntent.putExtra(ConstantValue.EXTRA_TYPE, cmdID);
			            Bundle bundle=new Bundle();
			            bundle.putByte(ConstantValue.EXTRA_ID, commNum);
			            bundle.putByteArray(ConstantValue.EXTRA_BYTES, data);
			            
			            myIntent.putExtra(ConstantValue.EXTRA_BUNDLE, bundle);
			            
			            myIntent.setAction(ConstantValue.CMD_RECEIVER);  
			            mContext.sendBroadcast(myIntent);  
						break;
						
					}
					}
					  pkt_in.setData(buf_in1);
				}
				catch(IOException e)
				{
			//		e.equals(IOException.)
			//		LogUtil.i(TAG, "RecvControlCmd.run() -- catch IOException: receive() " + e.getMessage());
				}
				finally
				{
			//		LogUtil.i(TAG, "RecvControlCmd.run() -- finally !!");
				}
			}
			so_in.close();
	        so_out.close();
		}
		catch (SocketException e)
		{ 
			LogUtil.e(TAG, "RecvControlCmd.run() -- catch SocketException: " , e);
        }
//		catch(IOException e)
//		{
//			LogUtil.i(TAG, "RecvControlCmd.run() -- catch IOException: " + e.getLocalizedMessage());
//		}
		catch(Exception e)
		{
			LogUtil.e(TAG, "RecvControlCmd.run() -- catch Exception: " , e);
		}
		finally
		{
		}	
		LogUtil.i(TAG, "RecvControlCmd.run() -- exit!");	
	}

}
